package com.example.kotlin.design.pattern.proxy;



import org.jetbrains.annotations.NotNull;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ConnectorManagerProxy {

    @NotNull
    public IConnectorManager connectorManager;

    private final IConnectorManager targetObject = ConnectorManager.getInstance();

    public static IConnectorManager getProxy() {
        return getInstance().connectorManager;
    }

    private ConnectorManagerProxy() {
        connectorManager = create(IConnectorManager.class);
    }

    public <T> T create(final Class<T> service) {
        return (T) Proxy.newProxyInstance(
                        service.getClassLoader(),
                        new Class<?>[]{service},
                        new InvocationHandler() {

                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) {

                                Annotation[] annotations = method.getAnnotations();
                                boolean check = isNeedCheck(annotations);
                                if (!check) {
                                    return invokeTargetMethod(method, args);
                                }
                                onCheckColorToken(method, args);
                                return null;
                            }
                        });
    }

    private void onCheckColorToken(Method method, Object[] args) {
        System.out.println("onCheckColorToken");
        invokeTargetMethod(method, args);
//        VerifyColorTokenManager.OnCheck onCheck = new VerifyColorTokenManager.OnCheck() {
//            @Override
//            public void onPass(String serverTime) {
//                ConnectorManager.logger(getClass(), "<-- " + method.getName() + ", VerifyColorToken success.");
//                invokeTargetMethod(method, args);
//            }
//
//            @Override
//            public void onFailed(String code, String desc) {
//                ConnectorManager.logger(getClass(), "<-- " + "VerifyColorToken failed, code = " +  code + ", desc = " + desc);
//                if (args == null) {
//                    // 目标函数没有参数；
//                    // 公共回调函数处理中已经添加token失效的处理，跳转到登陆界面
//                    return;
//                }
//                if (StatCodeConstants.IGNORE_CODE.equals(code)) {
//                    return;
//                }
//                // 回调函数的索引，接口api中callback函数必须是最后一个参数
//                int callbackIndex = args.length - 1;
//                if (args[callbackIndex] instanceof AbsConnectorCallBack) {
//                    if (Integer.parseInt(code) == ExceptionUtils.NET_CODE_UNKOWN_HOST) {
//                        code = HTTP_ERROR_NETWORK;
//                    } else if (StringUtils.equals(code, StatCodeConstants.CODE_103126)) {
//                        code = INVALID_REFRESH_TOKEN;
//                    }
//                    MbbResp mbbResp = new MbbResp(code, desc);
//                    ((AbsConnectorCallBack) args[callbackIndex]).onFailed(mbbResp);
//                }
//            }
//        };
//        ConnectorManager.logger(getClass(), "--> " + method.getName() + ", VerifyColorToken start...");
//        VerifyColorTokenManager.verify(onCheck);
    }

    /**
     * 检测是否需要进行彩色服务token的校验
     * @param annotations
     * @return
     */
    private boolean isNeedCheck(Annotation[] annotations) {
        boolean check = false;
        for (Annotation annotation : annotations) {
            if (annotation instanceof CheckColorToken){
                check = true;
                break;
            }
        }
        return check;
    }

    /**
     * 调用被代理的方法
     * @param method
     * @param args
     * @return
     */
    private Object invokeTargetMethod(Method method, Object[] args) {
        Object object = null;
        try {
            object = method.invoke(this.targetObject, args);
        } catch (IllegalAccessException | InvocationTargetException e) {
            //ConnectorManager.logger(getClass(), e);
        }
        return object;
    }

    private static ConnectorManagerProxy getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static final ConnectorManagerProxy INSTANCE = new ConnectorManagerProxy();
    }
}
